package net.qhzw.vip.qiyu.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import ma.glasnost.orika.MapperFacade;
import net.qhzw.vip.qiyu.dto.*;
import net.qhzw.vip.qiyu.entity.ProdAudit;
import net.qhzw.vip.qiyu.entity.ProdTagReference;
import net.qhzw.vip.qiyu.entity.Product;
import net.qhzw.vip.qiyu.entity.Sku;
import net.qhzw.vip.qiyu.handler.ApiException;
import net.qhzw.vip.qiyu.mapper.ProdTagReferenceMapper;
import net.qhzw.vip.qiyu.mapper.ProductMapper;
import net.qhzw.vip.qiyu.mapper.SkuMapper;
import net.qhzw.vip.qiyu.param.ProductParam;
import net.qhzw.vip.qiyu.service.*;
import net.qhzw.vip.qiyu.util.Arith;
import net.qhzw.vip.qiyu.util.PageAdapter;
import net.qhzw.vip.qiyu.util.PageParam;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {


    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private SkuMapper skuMapper;

    @Autowired
    private AttachFileService attachFileService;

    @Autowired
    private ProdTagReferenceMapper prodTagReferenceMapper;


    @Autowired
    private ProdAuditService prodAuditService;


    @Autowired
    private SkuService skuService;


    @Autowired
    private MapperFacade mapperFacade;

    @Autowired
    private BasketService basketService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveProduct(Product product) {
        productMapper.insert(product);
        if (CollectionUtil.isNotEmpty(product.getSkuList())) {
            for (Sku sku : product.getSkuList()) {
                sku.setProdId(product.getProdId());
                sku.setPlatformFee(Arith.mul(sku.getPrice(), 0.03));
                skuMapper.insert(sku);
            }
            //skuMapper.insertBatch(product.getProdId(), product.getSkuList());
        }
        prodTagReferenceMapper.insertBatch(product.getShopId(), product.getProdId(), product.getTagList());

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Caching(evict = {
            @CacheEvict(cacheNames = "product", key = "#product.prodId"),
            @CacheEvict(cacheNames = "skuList", key = "#product.prodId")
    })
    public void updateProduct(Product product, Product dbProduct) {
        product.setPlatformFee(product.getSkuList().get(0).getPlatformFee());
        productMapper.updateById(product);
        List<Long> dbSkuIds = dbProduct.getSkuList().stream().map(Sku::getSkuId).collect(Collectors.toList());
        // 将所有该商品的sku标记为已删除状态
        skuMapper.deleteByProdId(product.getProdId());
        // 接口传入sku列表
        List<Sku> skuList = product.getSkuList();
        if (CollectionUtil.isEmpty(skuList)) {
            return;
        }
        List<Sku> insertSkuList = new ArrayList<>();
        for (Sku sku : skuList) {
            sku.setIsDelete(0);
            sku.setStatus(product.getStatus());
            // 如果数据库中原有sku就更新，否者就插入
            if (dbSkuIds.contains(sku.getSkuId())) {
                skuMapper.updateById(sku);
            } else {
                insertSkuList.add(sku);
            }
        }
        // 插入sku
        if (CollectionUtil.isNotEmpty(insertSkuList)) {
            //skuMapper.insertBatch(product.getProdId(), insertSkuList);
            for (Sku sku : insertSkuList) {
                sku.setProdId(product.getProdId());
                skuMapper.insert(sku);
            }
        }
        //更新分组信息
        List<Long> tagList = product.getTagList();
        if (CollectionUtil.isNotEmpty(tagList)) {
            prodTagReferenceMapper.delete(new LambdaQueryWrapper<ProdTagReference>().eq(ProdTagReference::getProdId, product.getProdId()));
            prodTagReferenceMapper.insertBatch(dbProduct.getShopId(), product.getProdId(), tagList);
        }
    }


    @Override
    //@Cacheable(cacheNames = "product", key = "#prodId")
    public Product getProductByProdId(Long prodId) {

        //return productMapper.selectById(prodId);
        return getById(prodId);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    @Caching(evict = {
            @CacheEvict(cacheNames = "product", key = "#prodId"),
            @CacheEvict(cacheNames = "skuList", key = "#prodId")
    })
    public void removeProductByProdId(Long prodId) {
        Product dbProduct = getProductByProdId(prodId);

        productMapper.deleteById(prodId);


        skuMapper.deleteByProdId(prodId);
        skuService.remove(new LambdaQueryWrapper<Sku>()
                .eq(Sku::getProdId, prodId)
                .eq(Sku::getIsDelete, 1));
        //删除商品关联的分组标签
        prodTagReferenceMapper.delete(new LambdaQueryWrapper<ProdTagReference>()
                .eq(ProdTagReference::getProdId, prodId));

        // 删除数据库中的商品图片
//        if (StrUtil.isNotBlank(dbProduct.getImgs())) {
//            String[] imgs = dbProduct.getImgs().split(StrUtil.COMMA);
//            for (String img : imgs) {
//                attachFileService.deleteFile(img);
//            }
//        }
    }

    @Override
    @Caching(evict = {
            @CacheEvict(cacheNames = "product", key = "#prodId"),
            @CacheEvict(cacheNames = "skuList", key = "#prodId")
    })
    public void removeProductCacheByProdId(Long prodId) {

    }


    public Product getProductDtoByProdId(Long prodId) {
        return productMapper.selectProductById(prodId);
    }

    @Override
    public IPage<ProductDto> pageByPutawayTime(IPage<ProductDto> page) {
        return productMapper.pageByPutawayTime(page);
    }

    @Override
    public IPage<ProductDto> pageByTagId(Page<ProductDto> page, Long tagId) {
        return productMapper.pageByTagId(page, tagId);
    }

    @Override
    public IPage<ProductDto> moreBuyProdList(Page<ProductDto> page) {
        return productMapper.moreBuyProdList(page);
    }

    @Override
    public IPage<ProductDto> pageByCategoryId(Page<ProductDto> page, Long categoryId) {
        return productMapper.pageByCategoryId(page, categoryId);
    }

    @Override
    public List<Product> listProdByCategoryId(Long categoryId) {
        return productMapper.listProdByCategoryId(categoryId);
    }

    @Override
    public IPage<SearchProdDto> getSearchProdDtoPageByProdName(Page page, String prodName, Integer sort, Integer orderBy) {
        IPage<SearchProdDto> searchProdDtoPage = productMapper.getSearchProdDtoPageByProdName(page, prodName, sort, orderBy);
        for (SearchProdDto searchProdDto : searchProdDtoPage.getRecords()) {
            //计算出好评率
            if (searchProdDto.getPraiseNumber() == 0 || searchProdDto.getProdCommNumber() == 0) {
                searchProdDto.setPositiveRating(0.0);
            } else {
                searchProdDto.setPositiveRating(Arith.mul(Arith.div(searchProdDto.getPraiseNumber(), searchProdDto.getProdCommNumber()), 100));
            }
        }
        return searchProdDtoPage;
    }

    @Override
    public List<TagProductDto> tagProdList() {
        return productMapper.tagProdList();
    }

    @Override
    public IPage<ProductDto> collectionProds(PageParam page, Long userId) {
        return productMapper.collectionProds(page, userId);
    }


    /**
     * 查询上架商品
     *
     * @param page
     * @param productParam
     * @return
     */
    @Override
    public IPage<Product> listingProducts(PageParam<Product> page, ProductParam productParam) {
        List<Product> products = productMapper.selectByList(new PageAdapter(page), productParam);
        page.setRecords(products);
        page.setTotal(productMapper.selectByListTotal(productParam));
        return page;
    }


    /**
     * 商品上架审核
     *
     * @param productAudit
     * @return
     */
    @Override
    @Transactional
    public boolean productAudit(ProductAudit productAudit) {
        ProdAudit prodAudit = new ProdAudit();

        prodAudit.setId(IdWorker.getId());
        prodAuditService.save(prodAudit);

        Product dbProduct = getProductByProdId(productAudit.getProdId());
        if (dbProduct.getStatus() != 2) {
            throw new ApiException("请先上架后再, 审核!");
        }
        List<Sku> dbSkus = skuService.listByProdId(dbProduct.getProdId());

        Product product = mapperFacade.map(productAudit, Product.class);
        product.setUpdateTime(new Date());
        dbProduct.setSkuList(dbSkus);
        updateProduct(product, dbProduct);

        List<String> userIds = basketService.listUserIdByProdId(product.getProdId());
        for (String userId : userIds) {
            basketService.removeShopCartItemsCacheByUserId(userId);
        }
        for (Sku sku : dbSkus) {
            skuService.removeSkuCacheBySkuId(sku.getSkuId(), sku.getProdId());
        }

        return true;
    }

    @Override
    public IPage<ProductVo> findPage(PageParam<Product> page, ProductParam product) {
        List<Product> products = productMapper.selectByList(new PageAdapter(page), product);
        Long total = productMapper.selectByListTotal(product);

        List<ProductVo> records = null;
        if (!CollectionUtil.isEmpty(products)) {
            List<Long> list = products.stream().map(Product::getProdId).collect(Collectors.toList());
            List<ProdAudit> lists = prodAuditService.getByIds(list);
            records = new ArrayList<>(products.size());
            for (Product record : products) {
                ProductVo productVo = new ProductVo();
                BeanUtils.copyProperties(record, productVo);
                for (ProdAudit prodAudit : lists) {
                    if (record.getProdId().equals(prodAudit.getProdId())) {
                        productVo.setProdAudit(prodAudit);
                        continue;
                    }
                }
                records.add(productVo);
            }
        }

        IPage<ProductVo> pageInfo = new Page();
        pageInfo.setRecords(records);
        pageInfo.setTotal(total);
        return pageInfo;
    }


}

